#ifndef PCG_EXPR_H
#define PCG_EXPR_H

#include <stdio.h>

#define EXP_PLUS 0
#define EXP_MINUS 1
#define EXP_MULT 2
#define EXP_DIV 3
#define EXP_UMINUS 4
#define EXP_POW 5
#define EXP_ID 6
#define EXP_FUNC 7
#define EXP_NUMBER 8
#define EXP_PAREN 9
#define EXP_LT 10
#define EXP_GT 11
#define EXP_AND 12
#define EXP_OR 13
#define EXP_NOT 14

#ifndef NULL
#define NULL ((void*)0)
#endif

struct _pcg_expr_t;
struct _pcg_exprlist_t;

struct _pcg_exprlist_t {
	struct _pcg_expr_t *head;
	struct _pcg_exprlist_t *tail;
};

struct _pcg_expr_t {
	int type;
	union {
		char *sval;
		double dval;
	} lval;
	
	struct _pcg_exprlist_t *args;
	struct _pcg_expr_t *left, *right;
};

typedef struct _pcg_expr_t pcg_expr_t;
typedef struct _pcg_exprlist_t pcg_exprlist_t;

pcg_expr_t *pcg_expr_create(int type, ...);
pcg_expr_t *pcg_expr_create_number(double dval);
pcg_expr_t *pcg_expr_create_id(char *sval);
pcg_expr_t *pcg_expr_create_binary(int type, pcg_expr_t *left, pcg_expr_t *right);
pcg_expr_t *pcg_expr_create_func(char *sval, pcg_exprlist_t *args);
void pcg_expr_delete(pcg_expr_t *e);
void pcg_expr_destroy(pcg_expr_t *e);

pcg_exprlist_t *pcg_exprlist_create(pcg_expr_t *e);
void pcg_exprlist_delete(pcg_exprlist_t *el);
void pcg_exprlist_destroy(pcg_exprlist_t *el);
pcg_exprlist_t *pcg_exprlist_cons(pcg_exprlist_t *el, pcg_expr_t *e);
int pcg_exprlist_length(pcg_exprlist_t *el);

// debug routines
void pcg_exprlist_print(pcg_exprlist_t *el);
void pcg_expr_print(pcg_expr_t *e);

#endif // EXPR_H